package com.whc.common.utils;

public class SnowflakeIdGenerator {

    // 数据中心ID和机器ID（各2位，取值范围0-3）
    private final long dataCenterId;
    private final long machineId;

    // 严格控制各部分位数，保证总和≤49位（15位十进制最大为10^15-1 ≈ 2^49.5）
    private static final long DATA_CENTER_ID_BITS = 2L;  // 4个数据中心
    private static final long MACHINE_ID_BITS = 2L;      // 每数据中心4台机器
    private static final long SEQUENCE_BITS = 5L;        // 32个序列/ms

    // 最大值计算
    private static final long MAX_DATA_CENTER_ID = (1L << DATA_CENTER_ID_BITS) - 1;
    private static final long MAX_MACHINE_ID = (1L << MACHINE_ID_BITS) - 1;
    private static final long MAX_SEQUENCE = (1L << SEQUENCE_BITS) - 1;

    // 时间戳起点设为最近时间（2024年）
    private static final long EPOCH = 1704067200000L; // 2024-01-01 00:00:00 GMT

    // 偏移量计算
    private static final long MACHINE_ID_SHIFT = SEQUENCE_BITS;
    private static final long DATA_CENTER_ID_SHIFT = SEQUENCE_BITS + MACHINE_ID_BITS;
    private static final long TIMESTAMP_SHIFT = SEQUENCE_BITS + MACHINE_ID_BITS + DATA_CENTER_ID_BITS;

    // 最大有效时间戳（保证生成的ID≤999,999,999,999,999）
    private static final long MAX_VALID_TIMESTAMP = (999_999_999_999_999L >> TIMESTAMP_SHIFT) + EPOCH;

    private long lastTimestamp = -1L;
    private long sequence = 0L;

    public SnowflakeIdGenerator(long dataCenterId, long machineId) {
        if (dataCenterId > MAX_DATA_CENTER_ID || dataCenterId < 0) {
            throw new IllegalArgumentException("数据中心ID范围 0-" + MAX_DATA_CENTER_ID);
        }
        if (machineId > MAX_MACHINE_ID || machineId < 0) {
            throw new IllegalArgumentException("机器ID范围 0-" + MAX_MACHINE_ID);
        }
        this.dataCenterId = dataCenterId;
        this.machineId = machineId;
    }

    public synchronized long generateId() {
        long timestamp = System.currentTimeMillis();

        // 检查时间戳有效性
        if (timestamp > MAX_VALID_TIMESTAMP) {
            throw new RuntimeException("系统时间超出有效范围，可能导致ID超过15位");
        }

        // 时钟回拨检查
        if (timestamp < lastTimestamp) {
            throw new RuntimeException("时钟回拨异常，拒绝生成ID");
        }

        // 同一毫秒内生成
        if (timestamp == lastTimestamp) {
            sequence = (sequence + 1) & MAX_SEQUENCE;
            if (sequence == 0) {
                timestamp = waitForNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0;
        }

        lastTimestamp = timestamp;

        // 生成ID（时间戳部分已确保不会溢出）
        return ((timestamp - EPOCH) << TIMESTAMP_SHIFT)
                | (dataCenterId << DATA_CENTER_ID_SHIFT)
                | (machineId << MACHINE_ID_SHIFT)
                | sequence;
    }

    private long waitForNextMillis(long lastTimestamp) {
        long timestamp;
        do {
            timestamp = System.currentTimeMillis();
            // 再次检查时间戳有效性
            if (timestamp > MAX_VALID_TIMESTAMP) {
                throw new RuntimeException("等待时检测到系统时间超出范围");
            }
        } while (timestamp <= lastTimestamp);
        return timestamp;
    }

    // 验证方法（可选）
    public static void main(String[] args) {
        SnowflakeIdGenerator generator = new SnowflakeIdGenerator(3, 3);

        // 生成极端情况ID：最大时间戳+最大序列
        long maxId = ((MAX_VALID_TIMESTAMP - EPOCH) << TIMESTAMP_SHIFT)
                | (3 << DATA_CENTER_ID_SHIFT)
                | (3 << MACHINE_ID_SHIFT)
                | MAX_SEQUENCE;

        System.out.println("理论最大ID: " + maxId);
        System.out.println("实际长度: " + String.valueOf(maxId).length());

        // 实际生成测试
        for (int i = 0; i < 10; i++) {
            long id = generator.generateId();
            System.out.println("生成ID: " + id + " (长度: " + String.valueOf(id).length() + ")");
        }
    }
}